package com.databing.demo.greendao

import android.os.Bundle
import android.util.Log
import android.view.View
import com.databing.demo.R
import com.databing.demo.annotation.ClazzInfo
import com.databing.demo.base.TitleActivity
import com.databing.demo.config.TAG
import com.databing.demo.greendao.db.DaoMaster
import com.databing.demo.greendao.db.DaoSession
import com.databing.demo.greendao.db.StsActionBeanDao
import com.databing.demo.greendao.model.StsActionBean
import com.google.gson.Gson
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import org.greenrobot.greendao.async.AsyncOperation
import org.greenrobot.greendao.async.AsyncOperationListener
import org.greenrobot.greendao.async.AsyncSession


@ClazzInfo(2, 0, "第二章", "greenDao的数据的异步写入和读取")
class GreenDaoActivity : TitleActivity() {

    private lateinit var mDaoSession: DaoSession

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_green_dao)

        mDaoSession = DaoMaster.newDevSession(this, "greenDao")
    }

    fun onAdd(view: View) {
        for (index in 1..10) {
            Thread {
                insertStsActionList(initList())
            }.start()
        }

    }

    fun onDel(view: View) {
        addSubscribe(
            readStsActionList().subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({ data ->
                    deleteStsActionList(data)
                }) {
                    Log.e(TAG, it.toString())
                })
    }

    fun onModify(view: View) {
        addSubscribe(
            readStsActionList().subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({ data ->
                    for (item in data) item.state = 1
                    onModify(data)
                }) {
                    Log.e(TAG, it.toString())
                })
    }

    private fun onModify(list: List<StsActionBean>) {
        addSubscribe(
            updateStsActionList(list).subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({ data ->
                    if (data) {
                        readStsActionList()
                    }
                }) {
                    Log.e(TAG, it.toString())
                })
    }

    fun onQuery(view: View) {
        addSubscribe(
            readStsActionList().subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({ data ->
                    Log.e(TAG, Gson().toJson(data))
                }) {
                    Log.e(TAG, it.toString())
                })
    }

    private fun initList(): List<StsActionBean> {
        val list: MutableList<StsActionBean> = ArrayList()
        for (index in 1..10) {
            list.add(StsActionBean("$index", "$index content"))
        }
        return list
    }


    /**
     * 异步的数据插入，不用考虑数据同步的问题，AsyncSession底部通过LinkedBlockingQueue实现
     */
    private fun insertStsActionList(list: List<StsActionBean>) {
        val asyncSession: AsyncSession = mDaoSession.startAsyncSession()
        asyncSession.listener = AsyncOperationListener { operation: AsyncOperation? ->
            if (operation != null) {
                Log.e(TAG, "Success ${operation.isCompleted}")
            }
        }
        asyncSession.insertInTx(StsActionBean::class.java, list)
    }

    fun updateStsActionList(list: List<StsActionBean>): Flowable<Boolean> {
        return Flowable.create({ emitter ->
            val asyncSession: AsyncSession = mDaoSession.startAsyncSession()
            asyncSession.listener = AsyncOperationListener { operation: AsyncOperation? ->
                if (operation != null && operation.isCompletedSucessfully) {
                    emitter.onNext(true)
                } else {
                    emitter.onNext(false)
                }
                emitter.onComplete()
            }
            asyncSession.updateInTx(StsActionBean::class.java, list)
        }, BackpressureStrategy.BUFFER)
    }

    fun deleteStsActionList(list: List<StsActionBean?>?) {
        if (list == null || list.isEmpty()) return
        val asyncSession: AsyncSession = mDaoSession.startAsyncSession()
        asyncSession.deleteInTx(StsActionBean::class.java, list)
    }

    fun deleteExpiredSts(list: List<StsActionBean?>?) {
        if (list == null || list.isEmpty()) return
        val asyncSession: AsyncSession = mDaoSession.startAsyncSession()
        val qb = mDaoSession.stsActionBeanDao.deleteInTx(list)
    }

    fun readStsActionList(): Flowable<List<StsActionBean>> {
        return Flowable.create({ emitter ->
            val asyncSession: AsyncSession = mDaoSession.startAsyncSession()
            asyncSession.listener = AsyncOperationListener { operation: AsyncOperation? ->
                if (operation != null && operation.isCompletedSucessfully) {
                    val list: MutableList<StsActionBean> = ArrayList()
                    if (operation.result is List<*>) {
                        for (item in (operation.result as List<*>)) {
                            if (item is StsActionBean) list.add(item)
                        }
                    }
                    emitter.onNext(list)
                } else {
                    emitter.onNext(ArrayList())
                }
                emitter.onComplete()
            }

            val qb = mDaoSession.stsActionBeanDao.queryBuilder().limit(10)
                .where(StsActionBeanDao.Properties.State.eq(1))
            asyncSession.queryList(qb.build())
        }, BackpressureStrategy.BUFFER)
    }


}
